#ifndef __baker_Pair_h__
#define __baker_Pair_h__

namespace baker
{
    /** A template for a pair of value
    */
    template < typename T1
             , typename T2
             >
    struct Pair
    {
    public:
        T1 _1;
        T2 _2;

        /** Construct a Pair using T1 and T2's default constructors
        */
        Pair()
            : _1( T1() )
            , _2( T2() )
        {
        }

        /** Construct a Pair with initialize value
        */
        Pair( const T1 & t1
            , const T2 & t2
            )
            : _1( t1 )
            , _2( t2 )
        {
        }
    };

    /** create a Pair
    */
    template< typename T1
            , typename T2
            >
    static inline Pair<T1, T2> pair ( const T1 & t1
                                    , const T2 & t2
                                    )
    {
        return Pair<T1, T2>( t1, t2 );
    }

    /** Operator &lt;&lt; by using T1 and T2's operator &lt;&lt;;
        Mainly used with std::ostream.
    */
    template< typename S, typename T1, typename T2 >
    S & operator << ( S & stream
                    , const Pair<T1, T2> & p
                    )
    {
        stream << p._1 << p._2;

        return stream;
    }


    /** Operator ==; make use of T1 and T2's operator ==
    */
    template< typename T1, typename T2 >
    bool operator ==    ( const Pair<T1, T2> & lhs
                        , const Pair<T1, T2> & rhs
                        )
    {
        return ( lhs._1 == rhs._1 ) && ( lhs._2 == rhs._2 );
    }

    /** Operator == by using T1 and T2's operator &lt;. <br>
        If a &lt; b then either ( a._1 &lt; b._1 ) or ( a._2 &lt; b._2 ).
    */
    template< typename T1, typename T2 >
    bool operator < ( const Pair<T1, T2> & lhs
                    , const Pair<T1, T2> & rhs
                    )
    {
        return ( lhs._1 < rhs._1 ) or ( lhs._2 < rhs._2 );
    }
}

#endif  // __baker_Pair_h__
